package ${initProjectVo.packageName}.security.config;

import ${initProjectVo.packageName}.security.AccessAuthorizationManager;
import ${initProjectVo.packageName}.security.JwtAuthenticationTokenFilter;
import ${initProjectVo.packageName}.security.MyUserDetailsService;
import ${initProjectVo.packageName}.security.filter.CustomerUsernamePasswordAuthenticationFilter;
import ${initProjectVo.packageName}.security.handler.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.AuthorizationFilter;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import javax.servlet.http.HttpServletRequest;

@Configuration
public class SecurityConfig {
	@Autowired
	MyAuthenticationEntryPoint myAuthenticationEntryPoint;
	@Autowired
	MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
	@Autowired
	MyAuthenticationFailureHandler myAuthenticationFailureHandler;
	@Autowired
	private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource;
	@Autowired
	MyUserDetailsService myUserDetailsService;
	@Autowired
	MyLogoutSuccessHandler myLogoutSuccessHandler;
	@Autowired
	MyAccessDeniedHandler myAccessDeniedHandler;
	@Autowired
	JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
	@Autowired
	AccessAuthorizationManager accessAuthorizationManager;
	@Autowired
	AuthenticationConfiguration authenticationConfiguration;

	private static String ignoredUrl;

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
		return http.csrf().disable()
			.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
			.and()
			.httpBasic().authenticationEntryPoint(myAuthenticationEntryPoint)
			.and()//过滤非权限认证
			.authorizeRequests().anyRequest().authenticated()
			//                .authenticated().anyRequest().access("@rbacauthorityservice.hasPermission(request,authentication)")
			.and()
			.formLogin()
			.authenticationDetailsSource(authenticationDetailsSource)
			.and()
			.logout().logoutUrl("/api/logout")
			.logoutSuccessHandler(myLogoutSuccessHandler).permitAll().and().userDetailsService(myUserDetailsService)
			.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler).and()
			.addFilterAt(customerUsernamePasswordAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class)
			.addFilterBefore(authorizationFilter(), FilterSecurityInterceptor.class)
			.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class).build();
	}

	@Bean
	public WebSecurityCustomizer webSecurityCustomizer(){
		return (web) -> web.ignoring().antMatchers(ignoredUrl.split(","));
	}

	public static String getIgnoredUrl() {
		return ignoredUrl;
	}

	@Value("${ignored.urls}")
	public  void setIgnoredUrl(String ignoredUrl) {
		this.ignoredUrl = ignoredUrl;
	}
	/**
	* BCrypt加密
	* @return
	*/
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	@Bean
	public AuthenticationManager authenticationManager() throws Exception{
		return authenticationConfiguration.getAuthenticationManager();
	}

	private AuthorizationFilter authorizationFilter(){
		return new AuthorizationFilter(accessAuthorizationManager);
	}
	@Bean
	public CustomerUsernamePasswordAuthenticationFilter customerUsernamePasswordAuthenticationFilter() throws Exception {
		CustomerUsernamePasswordAuthenticationFilter customerUsernamePasswordAuthenticationFilter = new CustomerUsernamePasswordAuthenticationFilter();
		customerUsernamePasswordAuthenticationFilter.setFilterProcessesUrl("/api/login");
		customerUsernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
		customerUsernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
		customerUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
		return customerUsernamePasswordAuthenticationFilter;
	}



}
